#ifndef CIRQUEUE_H_
#define CIRQUEUE_H_

#include<iostream>
#include "Public.h"
#include<cstdlib>
using namespace std;

template <typename Type>
class CirQueue {

public:
	CirQueue();
	~CirQueue();

	Status QueueClear();
	bool isEmpty() const;
	bool isFull() const;

	int getLength() const;
	Type getHead() const;
	Status EnQueue(Type key);
	Type DeQueue();
	template <typename Type>
	friend ostream &operator<<(ostream &output, CirQueue<Type> &queue);

private:
	Type *m_pBase;
	int m_iFront;
	int m_iRear;
};

template<typename Type>
CirQueue<Type>::CirQueue() {
	m_pBase = new Type[MAXQSIZE];
	if (m_pBase == NULL) {
		perror("Memory allocation failed!Can't create a circular queue!");
		exit(EXIT_FAILURE);
	}
	m_iFront = m_iRear = 0;
}

template<typename Type>
CirQueue<Type>::~CirQueue() {
	delete[] m_pBase;
}

template<typename Type>
Status CirQueue<Type>::QueueClear()
{
	m_iFront = m_iRear = 0;
	return OK;
}

template<typename Type>
bool CirQueue<Type>::isEmpty() const {
	return m_iFront == m_iRear;
}

template<typename Type>
bool CirQueue<Type>::isFull() const {
	return m_iFront == (m_iRear + 1) % MAXQSIZE;
}

template<typename Type>
int CirQueue<Type>::getLength() const {
	return (m_iRear - m_iFront + MAXQSIZE) % MAXQSIZE;
}

template<typename Type>
Type CirQueue<Type>::getHead() const {

	return m_pBase[m_iFront];
}

template<typename Type>
Status CirQueue<Type>::EnQueue(Type key)
{
	int temp = (m_iRear + 1) % MAXQSIZE;
	if (temp == m_iFront) {
		cout << "FULL!" << endl;
		return ERROR;
	}
	m_pBase[m_iRear] = key;
	m_iRear = temp;

	return OK;
}

template<typename Type>
Type CirQueue<Type>::DeQueue() {
	if (isEmpty()) {
		return ERROR;
	}
	Type temp = getHead();
	m_iFront = (m_iFront + 1) % MAXQSIZE;
	return temp;
}

template<typename Type>
ostream &operator<<(ostream & output, CirQueue<Type> &queue) {

	for (int i = queue.m_iFront; i != queue.m_iRear;) {

		output << queue.m_pBase[i] << ' ';
		i = (i + 1) % MAXQSIZE;

	}
	output << endl;
	return output;
}

#endif



